package com.alvin.demo.utils;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

public class ResultHandler extends ChannelInboundHandlerAdapter {

    private final String commandStr ;

    private String resultStr ;

    public ResultHandler(String commandStr){
        this.commandStr = commandStr;
    }

    public String getResultStr() {
        return resultStr;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx){
        byte[] bytes = genRequestBytes(commandStr);
        ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes); // 发送byte数组时必须封装为 ByteBuf
        ctx.writeAndFlush(byteBuf); // 写入数据后必须flush,才能读取出数据
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.close() ;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg){
        ByteBuf buffer = (ByteBuf) msg;
        byte[] data = new byte[buffer.readableBytes()];
        buffer.readBytes(data);
        // 处理数据
        this.resultStr = bytes2HexString(data);
        buffer.release(); // 释放资源
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close() ;
    }

    // 将命令字符串转化为字节数组
    private byte [] genRequestBytes(String msg){
        byte[] bytes = hexString2Bytes(msg);//查询命令
        String[] ss = stringPolishing(getCRC(bytes));
        msg = msg + " " + ss[0] + " "  + ss[1];
        bytes = hexString2Bytes(msg);//再次获取带CRC是byte
        return bytes ;
    }

    // 4位CRC校验码，不足补0
    private static String[] stringPolishing(String Str) {
        int length = Str.length();
        StringBuilder StrBuilder = new StringBuilder(Str);
        for (int i = 0; i < (4 - length); i++) {
            StrBuilder.insert(0, "0");
        }
        String[] ss = new String[2];
        ss[0] = StrBuilder.substring(0, 2); // CRC 高位
        ss[1] = StrBuilder.substring(2); // CRC 低位
        return ss;
    }

    /**
     * 根据byte数组获取相应的 CRC 检验字符串
     * @param bytes 原始字符串的byte数组
     * @return 返回 CRC 检验字符串
     */
    private static String getCRC(byte[] bytes) {
        int CRC = 0x0000ffff;
        int POLYNOMIAL = 0x0000a001;

        for (byte b : bytes) {
            CRC ^= ((int) b & 0x000000ff);
            for (int j = 0; j < 8; j++) {
                if ((CRC & 0x00000001) != 0) {
                    CRC >>= 1;
                    CRC ^= POLYNOMIAL;
                } else {
                    CRC >>= 1;
                }
            }
        }
        return Integer.toHexString(CRC);
    }

    // 从字节数组到十六进制字符串转换
    private static String bytes2HexString(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF); // 将 byte转换为 16进制字符串
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex.toUpperCase()); // 转成大写
            if (i != bytes.length - 1){
                hexString.append(" ");
            }
        }
        return hexString.toString();
    }

    private static byte[] hexString2Bytes(String hexStr) {
        hexStr = hexStr.replace(" ", "");
        if (hexStr.length() % 2 != 0){
            throw new RuntimeException("操作指令不正确！！");
        }
        byte[] b = new byte[hexStr.length() / 2];
        int j = 0;
        for (int i = 0; i < b.length; i++) {
            char c0 = hexStr.charAt(j);
            char c1 = hexStr.charAt(j+1);
            j += 2;
            b[i] = (byte) Integer.parseInt(c0 + "" + c1, 16); // 将16进制字符串转 byte
        }
        return b;
    }
}